#pragma once
#include<iostream>
#include<experimental/filesystem>
#include<string>
#include<vector>
#include<fstream>
#include"bundle.h"
#include"./cpp-httplib-master/httplib.h"
#include<sys/stat.h>
namespace fs=std::experimental::filesystem;


namespace bundle{


    class FileUtil {

        public:
        FileUtil(const std::string& path) 
        : name_path(path) {
        }
        //获取文件的大小
        size_t getSize() {
            std::ofstream ofs(name_path,std::ios::binary | std::ios::app);
            size_t size =0;
            if(ofs.is_open()) {
               size=ofs.tellp();            
            } else {
                std::cerr << "Error opening file: " << name_path << std::endl;
            }
            //关不关都是一样的.
            ofs.close();
            return size;
        }
    
        //获取文件的最后修改时间和最后访问时间
    
        //  struct stat {
        //            dev_t     st_dev;         /* ID of device containing file */
        //            ino_t     st_ino;         /* Inode number */
        //            mode_t    st_mode;        /* File type and mode */
        //            nlink_t   st_nlink;       /* Number of hard links */
        //            uid_t     st_uid;         /* User ID of owner */
        //            gid_t     st_gid;         /* Group ID of owner */
        //            dev_t     st_rdev;        /* Device ID (if special file) */
        //            off_t     st_size;        /* Total size, in bytes */
        //            blksize_t st_blksize;     /* Block size for filesystem I/O */
        //            blkcnt_t  st_blocks;      /* Number of 512B blocks allocated */
    
        //            /* Since Linux 2.6, the kernel supports nanosecond
        //               precision for the following timestamp fields.
        //               For the details before Linux 2.6, see NOTES. */
    
        //            struct timespec st_atim;  /* Time of last access */
        //            struct timespec st_mtim;  /* Time of last modification */
        //            struct timespec st_ctim;  /* Time of last status change */
    
        //        #define st_atime st_atim.tv_sec      /* Backward compatibility */
        //        #define st_mtime st_mtim.tv_sec
        //        #define st_ctime st_ctim.tv_sec
        //        };
    
    
        size_t getLastModified() {
            struct stat file_stat;
            if(stat(name_path.c_str(),&file_stat) == 0) {
                return static_cast<size_t>(file_stat.st_mtime);
            } else {
                std::cerr << "Error getting last modified time for file: " << name_path << std::endl;
                return 0; // 返回0表示获取失败
            }
            return 0;
        }
    
    
    
    
        size_t getLastAccessed() {
            struct stat file_stat;
            if(stat(name_path.c_str(),&file_stat) == 0) {
                return static_cast<size_t>(file_stat.st_atime);
            } else {
                std::cerr << "Error getting last Accesssed time for file: " << name_path << std::endl;
                return 0; // 返回0表示获取失败
            }
            return 0;
        }
    
        //设置文件的内容与获取文件的内容
        bool setContent(const std::string& in_content) {
            std::ofstream ofs(name_path,std::ios::binary | std::ios::out);
            if(ofs.is_open()) {
                ofs.write(in_content.c_str(),in_content.size());
                ofs.close();
            } else {
                std::cerr << "Error opening file for writing: " << name_path << std::endl;
                return false;
            }
            return true;
        }
    
        //这个可以指定文件的获取范围和大小
        bool getContent( std::string& out_content,const size_t& pos,const size_t& len) {
            if(pos < 0 || len < 0 || pos + len > getSize()) {
                std::cerr << "Error: Read range exceeds file size." << std::endl;
                return false;
            }
            std::ifstream ifs(name_path,std::ios::binary | std::ios::in);
            if(ifs.is_open()) {
                ifs.seekg(pos);
                out_content.resize(len);
                ifs.read(&out_content[0], len);
                ifs.close();
            } else {
                std::cerr << "Error opening file for reading: " << name_path << std::endl;
                return false;
            }
            return true;
        }
    
    
        // bool getPartialContent();
        //获取目录的内容,也就是遍历这个目录判断当中的文件和子目录
        bool getDirContent(const std::string& path, std::vector<std::string>& out_content) {
            if(!fs::exists(path)) return false;
            for(const auto& entry : fs::directory_iterator(path)) {
                if(fs::is_regular_file(entry)) {
                    out_content.push_back(entry.path().string());
                } else if(fs::is_directory(entry)){
                    out_content.push_back(entry.path().string());
                    getDirContent(entry.path().string(),out_content);
                } else {
                    std::cerr << "Error: Unknown file type: " << entry.path().string() << std::endl;
                    return false;
                }
            }
            return true;
        }   
        //判断文件或者目录是否存在
        bool FileExists(const std::string& path) {
            return fs::exists(path);
        }
        //创建目录,如果已经存在就不再创建
        bool CreateDir(const std::string& path) {
            if(!fs::exists(path)) {
                //创建路径当中的所有目录
                return fs::create_directories(path);
            }
            return true;
        }
    
        //压缩和解压文件
        bool CompressFile(const std::string& in_path, const std::string& back_path) {
            // 使用压缩库进行压缩操作
            //1. 打开文件
            std::string body="";
            if(getContent(body,0,getSize())) {
                //2.进行压缩
                std::string compressed_data = bundle::pack(bundle::LZIP,body);
                //3.写入压缩后的数据到指定路径
                std::ofstream ofs(back_path, std::ios::binary | std::ios::out);
                if(ofs.is_open()) {
                    ofs.write(&compressed_data[0], compressed_data.size());
                    ofs.close();
                    return true;
                }
            } else {
                std::cerr << "Error reading file for compression: " << in_path << std::endl;
                return false;
            }
            return false;
        }
    
    
        bool UnCompressFile(const std::string& back_path, const std::string& in_path) {
            std::string Compressed_data="";
            std::string unpacked = "";
            if(getContent(Compressed_data,0,getSize()) == false) {
                std::cerr << "Error reading file for decompression: " << back_path << std::endl;
                return false;
            } else {
                unpacked =bundle::unpack(Compressed_data);
                std::ofstream ofs(in_path, std::ios::binary | std::ios::out);
                if(ofs.is_open()) {
                    ofs.write(&unpacked[0],unpacked.size());
                    ofs.close();
                    return true;
                } else {
                    std::cerr << "Error opening file for writing decompressed data: " << in_path << std::endl;
                    return false;
                }
            }
            return false;
        }
    
    
        private:
        std::string name_path;
    };
    
    class JsonUtil {
        public:
            //进行序列化,然后将str的字符串进行序列化,然后压缩到in_josn当中
            static bool Serialize(const Json::Value& in_josn,std::string& str) {
                Json::StreamWriterBuilder builder;
                std::unique_ptr<Json::StreamWriter> writer(builder.newStreamWriter());
                std::ostringstream ofs;
                if(writer->write(in_josn,&ofs) != 0) {
                    std::cerr << "Error serializing JSON" << std::endl;
                    return false;
                }
                str=ofs.str();
                return true;
            }
            //进行反序列化,将str的字符串进行反序列化,然后解压缩到in_josn当中
            static bool UnSerialize(const std::string& str,Json::Value& in_josn) {
                Json::CharReaderBuilder builder;
                std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
                std::string errs;
                if(!reader->parse(str.c_str(),str.c_str()+str.size(),&in_josn,&errs)) {
                    std::cerr << "Error parsing JSON: " << errs << std::endl;
                    return false;
                }
                return true;
            }
    }
    
}

